<?php

// sometimes a bad call will be made to last.fm that will result in a warning message popping up. 
// we don't want this in production
error_reporting(0);

// parent class for everything that uses the last.fm API
abstract class lastfm {
	private $api_key = '2e987f96a111132045e00afaf4d8fa99';
	private $endpoint = 'http://ws.audioscrobbler.com/2.0/';
	
	/* 
	 * get_json -- Calls API for a method and arguments, returns JSON
	 * Basically a helper method
	 *
	 * For example:
	 *     return json_decode(file_get_contents($endpoint?method=album.search&album=$search&api_key=$api_key&format=json"))
	 * where album.search is the method and album=$search is the argument
	 * is the same as
	 *     get_json('album.search', 'album=$search')
	 */
	protected function get_json($method, $args) {
		$api_key = $this->api_key;
		$endpoint = $this->endpoint;
		$json_url = "$endpoint?method=$method&$args&api_key=$api_key&format=json";
		return json_decode(file_get_contents($json_url));
	}
	
	// helper to @render() function
	// expects image array returned by serveral last.fm API calls
	// sizes are small, medium, large, and extralarge
	protected function get_image_url($image_array, $size) {
		foreach($image_array as $image_object) {
			foreach ($image_object as $key => $field) {
				if ($key == '#text' && $image_object->size == $size)
					return $field;
			}
		}
	}
	
	abstract function render();
}

class album extends lastfm {
	private $album_search_json;
	public $artist;
	public $album;
	
	// performs basic api album search, returns full JSON result
	public function __construct($album_name) {
		$album_name = prep_search_string($album_name);
		$this->album_search_json = $this->get_json('album.search', "album=$album_name&limit=1");
		$first_search_result = $this->album_search_json->results->albummatches->album;
		$this->artist = $first_search_result->artist;
		$this->album = $first_search_result->name;
	}
	
	// gets full cd info using artist and album found in contructor search
	// returns JSON
	private function cd_info_json() {
		$artist = urlencode($this->artist);
		$album = urlencode($this->album);
		return $this->get_json('album.getinfo', "artist=$artist&album=$album&autocorrect=1");
	}
	
	// renders a cover
	// sizes are small, medium, large, and extralarge
	public function get_cover($size = 'large') {
		$cd_object = $this->cd_info_json()->album;
		if ($cd_object)
			return $this->get_image_url($cd_object->image, $size);
		else
			return false;
	}
	
	// format cd data in HTML, expects full cd object as returned by last.fm API method album.getinfo
	public function render() {
		$cd_object = $this->cd_info_json()->album;
		if($cd_object) {
			//echo '<h2><a href="'. $cd_object->url .'">'. $cd_object->name .'</a> by '. $cd_object->artist .'</h2>';
			//echo '<p>released: '. date('F j, Y', strtotime($cd_object->releasedate)) .'</p>';
			//echo "<img src=\"{$this->get_cover('large')}\" alt=\"{$cd_object->name} album cover\">";
			echo '<h2>Tracklist</h2>';
			echo '<ol>';
			foreach($cd_object->tracks->track as $track) {
				echo '<li><a data-time="'. secs_to_mins($track->duration) .'" data-artist="'. $cd_object->artist .'" data-album="'. $cd_object->name .'" href="'. $track->url .'">'. $track->name .'</a></li>';
			}
			echo '</ol>';
		} else {
			display_old_player();
		}
	}
}

class artist extends lastfm {
	private $artist_json;
	private $tour_json;
	
	// gets artist info via artist name, returns full JSON result
	public function __construct($artist_name) {
		$artist_name = prep_search_string($artist_name);
		$this->artist_json = $this->get_json('artist.getInfo', "artist=$artist_name&autocorrect=1");
		$this->tour_json = $this->get_json('artist.getEvents', "artist=$artist_name&autocorrect=1&limit=3");
	}
	
	public function render_tour() {
		$venues = $this->tour_json->events->event;
		$artist = $this->artist_json->artist;
		if($venues) {
			echo '<h2>Upcoming shows for <a href="'. $artist->url .'">'. $artist->name .'</a></h2>';
			echo '<ul>';
			foreach($venues as $venue) {
				echo '<li>';
					echo '<p>';
					echo '<span class="date">'. date('<\s\p\a\n>M</\s\p\a\n> j', strtotime($venue->startDate)) .'</span> ';
					echo $venue->venue->name;
					echo '</p>';
					echo '<a title="view event page" href="'. $venue->url .'">show info &raquo;</a>';
				echo '</li>';
			}
			echo '<p id="more_shows">... <a href="'. $artist->url .'/+events">more shows on last.fm</a></p>';
			echo '</ul>';
		} else {
			// echo '<p>Tour info not found</p>';
			return false;
		}
	}
	
	// format artist data in HTML
	function render(){
		$artist = $this->artist_json->artist;
		if($artist) {
			echo '<h2>About <a href="'. $artist->url .'">'. $artist->name .'</a></h2>';
			if ($this->get_image_url($artist->image, 'large'))
				echo '<img src="'. $this->get_image_url($artist->image, 'large') .'" />';
			echo '<p>'. $artist->bio->summary .'</p>';
		} else {
			// echo '<p>Artist not found</p>';
			return false;
		}
	}
}

// get info for given venue
class venue extends lastfm {
	private $venue_search_json;
	private $venue_json;
	private $venue_id;
	
	// performs basic api venue search, returns full JSON result
	public function __construct($venue_name) {
		$venue_name = prep_search_string($venue_name);
		$this->venue_search_json = $this->get_json('venue.search', "venue=$venue_name&limit=10&country=US");
		$search_results = $this->venue_search_json->results->venuematches->venue;
		$this->venue_json = $this->find_boston_venue($search_results);
		$this->venue_id = $this->venue_json->id;
	}
	
	// goes through a list of venues and finds the venue from Boston
	// House of Blues, for example, has locations all over the place
	// naturally, this excludes venues outside of Boston, like major festivals
	private function find_boston_venue($venue_array) {
		// if the given value isn't an array, then only one value (or an error) was returned
		// and the JSON is formatted differently if it's just one value
		if(is_array($venue_array)) {
			foreach($venue_array as $key => $venue) {
				if(stristr($venue->location->city, 'boston'))
					return $venue;
			}
			// if the foreach loop doesn't find anything, return the first result
			return reset($venue_array);
		} else
			return $venue_array;
	}
	
	// gets full venue info using venue id found in contructor search
	// returns JSON
	private function venue_events_json() {
		return $this->get_json('venue.getEvents', "venue={$this->venue_id}");
	}
	
	public function get_image($size = 'extralarge') {
		return $this->get_image_url($this->venue_json->image, $size);
	}
	
	// format venue info and venue event data in HTML
	public function render() {
		$events = $this->venue_events_json()->events->event;
		if($events) {
			$location = $this->venue_json->location;
			$location_string = "{$location->street} {$location->city}, {$location->country} {$location->postalcode}";
			echo '<h2>';
				echo 'Upcoming shows @ <a href="'. $this->venue_json->url .'">'. $this->venue_json->name .'</a> ';
				echo '<span class="geo">(<a href="http://maps.google.com/?q='. $location_string .'">google map</a>)</span>';
			echo '</h2>';
			echo '<ul id="events">';
			$index = 1;
			foreach($events as $event) {
				echo '<li>';
					echo '<p>';
					echo '<span class="date">'. date('<\s\p\a\n>M</\s\p\a\n> j', strtotime($event->startDate)) .'</span> ';
					if(is_string($event->artists->artist)) {
						echo $event->artists->artist;
					} else {
						$artist_list = array();
						foreach($event->artists->artist as $artist)
							$artist_list[] = $artist;
						echo implode(', ', $artist_list);
					}
					echo '</p>';
					echo '<a title="view event page" href="'. $event->url .'">show info &raquo;</a> ';
				echo '</li>';
				
				if($index == 5) {
					echo '<p id="more_shows">... <a href="'. $this->venue_json->url .'">more shows on last.fm</a></p>';
					break;
				}
				
				$index++;
			}
			echo '</ul>';
		} else {
			// echo '<p>Venue not found</p>';
			return false;
		}
	}
}

?>